import {
  unref,
  h,
  computed,
  Component,
  ref,
  useAttrs,
  onUnmounted,
  toRef,
} from "vue";
import { IElsElem, ElsElemUtil, } from "../ElsElem"
import { InfoFilled } from "@element-plus/icons-vue"
import { IElsForm } from "./inter";
import { ElsFormUtil } from "./util";
//
import {
  ElForm,
  ElRadio,
  ElCheckbox,
  ElInput,
  ElFormItem,
  ElOption,
  ElTooltip,
  ElIcon,
} from "element-plus";
//
import {camelCase,has,get,set,merge,unset,isFunction} from "lodash-es"
//
import buildRules = ElsFormUtil.buildRules;
import buildElFormItemProps = ElsFormUtil.buildElFormItemProps;
import isNeedElFormItem = ElsFormUtil.isNeedElFormItem;
// tag 替换默认 tag 并 且当父元素为特定元素时，替换子元素默认 tag
export const tag: IElsElem.FunctionTag = ({ tag, parent }) => {
  if (tag) { return tag; }
  if (parent && has(EL_FORM_DEFAULT_CHILD, camelCase(parent.tagname))) {
    return EL_FORM_DEFAULT_CHILD[camelCase(parent.tagname)];
  }
  return ElInput;
};

export const render: IElsElem.RenderFunction = (config) => {
  const props = config.props;
  const setupRes = config.setupRes;
  // 判断是否是表单元素
  if (setupRes.isFormElem) {
    const prop = setupRes.formProp as string;
    unset(props, "value");
    // 判断是否需要自动添加 elFormItem
    if (setupRes.isNeedElFormItem) {
      // 生成 elFormItem 元素的 props
      const elFormItemProps: Record<string, any> = {
        ...buildElFormItemProps(props),
        prop,
      };
      // 生成 rules
      elFormItemProps.rules = buildRules(elFormItemProps);
      // 
      return h(ElFormItem, elFormItemProps, {
        default: () => ElsElemUtil.defaultRender(config),
        label: () => [elFormItemProps.label, elFormItemProps?.tip ? buildTip(elFormItemProps.tip) : '']
      });

    }
  }
  // 返回默认渲染函数
  return ElsElemUtil.defaultRender(config);
};

export const setup: IElsElem.SetupFunction = (props, params) => {
  const elem = props.elem;
  const { formProps, emitChange } = props.context as { formProps: IElsForm.UIPluginConfig["formProps"], emitChange: IElsForm.UIPluginConfig["emitChange"],formElemNames:string[] };
  const parent = props.parent;
  const tagname = camelCase(params.tagname);
  const parentname = camelCase(parent?.tagname);
  const setupRes = parent?.setupRes;
  const tp = unref(elem.prop);
  const ep: string = typeof tp === "function" ? tp(props) : tp;
  const fp: string | any[] = unref(setupRes?.formProp) || [];
  const p: string[] = /^\^/.test(ep) ? [ep.replace("^", "")] : new Array<string>().concat(fp, ep || []);
  const formProp = p.join(".");
  //
  const res: ReturnType<IElsElem.SetupFunction> = { isFormElem: false };
  //
  if (p.length > 0) {
    res.formProp = formProp;
  }
  // 是否是表单元素
  if (isFormElem(elem, tagname, parentname)) {
    res.isFormElem = true;
    if (elem.isFormElem !== false) {
      formProps?.add(formProp);
      const defaultValue = unref(elem.modelValue ?? elem.value) ?? undefined;
      const context = props.context;
      const formData = context?.formData;
      //
      if (get(unref(formData), formProp) == undefined) {
        set(unref(formData), formProp, defaultValue);
      }
      // 添加 v-model 指令 以及绑定交互事件
      res.prop = {
        ":modelValue": computed(() => get(unref(formData), formProp)),
        "onUpdate:modelValue": (v: any) => {
          set(unref(formData), formProp, v ?? defaultValue);
          emitChange?.(formProp, v);
        },
      };
    }
    res.excludeKeys = ["value"];
    res.isFormItem = true;
    res.isNeedElFormItem = isNeedElFormItem(elem);
    onUnmounted(() => {
      formProps?.delete(formProp);
    });
  }
  return res;
};

const useElForm: IElsForm.UIPluging = (props, cfg, ext) => {
  const size = unref(props.size) || "default";
  const attrs = useAttrs();
  //
  const formData = cfg.formData;
  // 默认的 elFormProps
  const defaultElFormProps: Record<string, any> = merge(
    { validateOnRuleChange: false, size },
    attrs.elForm || {}
  );
  //
  const elFormRef = ref<TypeElForm>();
  //
  const elem: IElsElem.Elem = {
    ...defaultElFormProps,
    tag: ElForm,
    ref: (e: TypeElForm) => (elFormRef.value = e),
    cls: toRef(props, "column"),
    model: formData,
  };
  //
  const elFormApi = (name: string, args: any[]) => {
    const f = get(unref(elFormRef), name);
    if (f && isFunction(f)) {
      return f(...args);
    }
  };
  //
  const context = {
    ...ext,
    formData: formData,
    formProps: cfg.formProps,
    emitChange: cfg.emitChange,
    tag,
    setup,
    render,
    excludeKeys:["isFormElem","isNeedElFormItem"],
    params: {
      ...ext,
      formData: formData,
      formProps: cfg.formProps,
    }
  };

  return {
    elem,
    context,
    formRef: elFormRef,
    formApi: elFormApi,
    refresh: () => { },
    validate: (...args: any[]) => elFormApi("validate", args),
  };
};

export default useElForm;

// ElForm 表单元素的 tagname  驼峰形式，首字符小写//
const EL_FORM_ELEM_TAGS = [
  "elInput",
  "elInputNumber",
  "elSelect",
  "elSelectV2",
  "elDatePicker",
  "elRadio",
  "elRadioGroup",
  "elCheckbox",
  "elCheckboxGroup",
  "elCascader",
  "elCascaderPanel",
  "elColorPicker",
  "elRate",
  "elSlider",
  "elSwitch",
  "elTimePicker",
  "elTimeSelect",
  "elTransfer",
  "elAutocomplete",
];
// 特殊父元素，可以凭借 父元素名称确定子元素名称的！
const EL_FORM_DEFAULT_CHILD: Record<string, Component> = {
  elCheckboxGroup: ElCheckbox,
  elRadioGroup: ElRadio,
  elSelect: ElOption,
};
//

type TypeElForm = InstanceType<typeof ElForm>;
// 是否是表单元素
export const isFormElem = (e: IElsElem.Elem, en: string, pn?: string) => {
  // isFormElem
  if (unref(e.isFormElem) === true) {
    return true;
  }
  //
  if (pn && has(EL_FORM_DEFAULT_CHILD, pn)) {
    return camelCase(EL_FORM_DEFAULT_CHILD[pn].name) !== en;
  }
  //
  if (!ElsFormUtil.SELF_FORM_NAMES.includes(en) && !EL_FORM_ELEM_TAGS.includes(en)) {
    return false;
  }
  return true;
};

export const buildTip = (tip: IElsForm.ColumnItem['tip']) => {
  if (tip == undefined || !tip) { return undefined }
  const t = typeof tip === 'string' ? { content: tip } : tip;
  //
  const D: IElsForm.ColumnTip = {
    // icon:InfoFilled,
    placement: "top-start",
    effect: "dark"
  }
  //
  const d: IElsForm.ColumnTip = { ...D, ...t };
  //
  return h(ElTooltip, d, { default: () => h(ElIcon, { style: "margin-left:1em;height:100%;color:#909399" }, { default: () => h(InfoFilled) }) })
}

